package com.xiaohong.user.controller;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaohong.user.interceptor.TokenRequestInterceptor;
import com.xiaohong.user.pojo.RegisterUser;
import com.xiaohong.user.pojo.User;
import com.xiaohong.user.service.UserService;
import entity.Result;
import entity.RoleCode;
import entity.StatusCode;
import entity.TokenDecode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

//import io.seata.spring.annotation.GlobalTransactional;

/*@Api：用在请求的类上，表示对类的说明
        tags="说明该类的作用，可以在UI界面上看到的注解"
        value="该参数没什么意义，在UI界面上也看到，所以不需要配置"

@ApiOperation：用在请求的方法上，说明方法的用途、作用
        value="说明方法的用途、作用"
        notes="方法的备注说明"

@ApiImplicitParams：用在请求的方法上，表示一组参数说明
@ApiImplicitParam：用在@ApiImplicitParams注解中，指定一个请求参数的各个方面
        name：参数名
        value：参数的汉字说明、解释
        required：参数是否必须传
        paramType：参数放在哪个地方
        · header --> 请求参数的获取：@RequestHeader
            · query --> 请求参数的获取：@RequestParam
            · path（用于restful接口）--> 请求参数的获取：@PathVariable
            · div（不常用）
                    · form（不常用）
                    dataType：参数类型，默认String，其它值dataType="Integer"
                    defaultValue：参数的默认值

@ApiResponses：用在请求的方法上，表示一组响应
@ApiResponse：用在@ApiResponses中，一般用于表达一个错误的响应信息
        code：数字，例如400
        message：信息，例如"请求参数没填好"
        response：抛出异常的类

@ApiModel：用于响应类上，表示一个返回响应数据的信息
        （这种一般用在post创建的时候，使用@RequestBody这样的场景，
        请求参数无法使用@ApiImplicitParam注解进行描述的时候）
@ApiModelProperty：用在属性上，描述响应类的属性*/

@Tag(name = "用户信息接口")
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;


    @GetMapping("/test1")
    public String test1(){
        return "test1放行";
    }

    @Operation(summary = "test2鉴权",description = "所需权限：无",security ={@SecurityRequirement(name ="Authorization")})
    @GetMapping("/test2")
    public String test2(){
        return "test2鉴权";
    }

    /**
     * 用户注册
     * @return
     */
    @PostMapping(value = "/register")
    @Operation(summary = "用户注册接口",description = "所需权限：无",security ={@SecurityRequirement(name ="Authorization")})
//    @GlobalTransactional
    public Result register(@RequestBody RegisterUser registerUser, HttpServletRequest request) {
        User user = new User();
        //获取用户登录IP地址
        user.setLastLoginIP(request.getHeader("ip"));
        user.setPhone(registerUser.getPhone());
        user.setEmail(registerUser.getEmail());
        User user1 = new User();
        user1.setPhone(registerUser.getPhone());
        if (userService.findList(user1).size() != 0){
            return new Result(true, StatusCode.LOGINERROR,"手机号已注册！");
        }
        if (registerUser.getPhone().trim() != null && registerUser.getPassword().trim() !=null && registerUser.getEmail() != null){
            //对用户密码进行加盐加密存入数据库
            user.setPassword(BCrypt.hashpw(registerUser.getPassword(), BCrypt.gensalt()));
            //最后登录时间
            user.setLastLoginTime(new Date());
            //设置权限
            user.setAuthorities(RoleCode.USER);
            //存入数据库
            userService.add(user);
            return new Result(true, StatusCode.OK,"注册成功！");
        }
        return new Result(true, StatusCode.LOGINERROR,"请求参数错误！");
    }

    /***
     * User分页条件搜索实现
     * @param User
     * @param page
     * @param size
     * @return
     */
    @Operation(summary = "User条件分页查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameters({
            @Parameter(in = ParameterIn.PATH, name = "page", description = "当前页", required = true),
            @Parameter(in = ParameterIn.PATH, name = "size", description = "每页显示条数", required = true)
    })
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<Page> findPage(@RequestBody(required = false) @Parameter(name = "User对象",required = true) User User, @PathVariable int page, @PathVariable int size){
        //调用UserService实现分页条件查询User
        Page pageInfo = userService.findPage(User, page, size);
        return new Result<Page>(true, StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * User分页搜索实现
     * @param page:当前页
     * @param size:每页显示多少条
     * @return
     */
    @Operation(summary = "User分页查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameters({
            @Parameter(in = ParameterIn.PATH, name = "page", description = "当前页", required = true),
            @Parameter(in = ParameterIn.PATH, name = "size", description = "每页显示条数", required = true)
    })
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<Page> findPage(@PathVariable int page, @PathVariable int size){
        // 调用UserService实现分页查询User
        Page pageInfo = userService.findPage(page, size);
        // 获取所有权限
        List<String> allList = new ArrayList<>();
        allList.add(RoleCode.USER);
        allList.add(RoleCode.VIP);
        allList.add(RoleCode.ILLEGAL);
        allList.add(RoleCode.ADMIN);
        allList.add(RoleCode.VISITOR);
        allList.add(RoleCode.OAUTH);
        //获取查询到的所有User对象
        List<User> list = pageInfo.getRecords();
        for (User user : list) {
            // 获取用户权限数组
            String[] split = user.getAuthorities().split(",");
            // 全部权限
            List<String> arrayList = new ArrayList<>();
            arrayList.addAll(allList);
            for (String s : split) {
                if (arrayList.contains(s))
                    arrayList.remove(s);
            }
            // 设置未授权权限
            user.setUnAuthorize(arrayList);
        }
        pageInfo.setRecords(list);
        return new Result<Page>(true, StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * 多条件搜索数据
     * @param User
     * @return
     */
    @Operation(summary = "User多条件查询",description = "所需权限：oauth",security ={@SecurityRequirement(name ="Authorization")})
    @PostMapping(value = "/search" )
    @PreAuthorize("hasAnyAuthority('oauth','admin')")
    public Result<List<User>> findList(@RequestBody(required = false) @Parameter(name = "User对象",required = true) User User){
        //调用UserService实现条件查询User
        List<com.xiaohong.user.pojo.User> list = userService.findList(User);
        return new Result<List<com.xiaohong.user.pojo.User>>(true, StatusCode.OK,"查询成功",list);
    }

    /***
     * 根据Id删除user数据
     * @param id
     * @return
     */
    @Operation(summary = "User根据ID删除",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameter(in = ParameterIn.PATH, name = "id", description = "主键ID", required = true)
    @DeleteMapping(value = "/{id}")
    public Result delete(@PathVariable Long id){
        //调用UserService实现根据主键删除
        userService.delete(id);
        return new Result(true, StatusCode.OK,"删除成功");
    }

    /***
     * 修改User数据
     * @param user
     * @return
     */
    @Operation(summary = "修改User数据",description = "所需权限： （需传id值，且要加引号包着）",security ={@SecurityRequirement(name ="Authorization")})
    @PutMapping
    public Result update(@RequestBody User user){
        //调用UserService实现修改User
        userService.update(user);
        return new Result(true, StatusCode.OK,"修改成功");
    }

    /***
     * 根据ID修改User数据
     * @param user
     * @return
     */
    @Operation(summary = "根据ID修改User",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameter(in = ParameterIn.PATH, name = "id", description = "主键ID", required = true)
    @PutMapping("/{id}")
    public Result updateById(@RequestBody @Parameter(name = "User对象",required = true) User user, @PathVariable(value = "id") Long id){
        // 补充id
        user.setId(id);
        //调用UserService实现修改User
        userService.updateById(user);
        return new Result(true, StatusCode.OK,"修改成功");
    }


    /***
     * 根据ID修改User权限
     * @param user
     * @return
     */
    @Operation(summary = "根据ID修改User权限",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @PutMapping("/authority")
    public Result updateAuthorityById(@RequestBody @Parameter(name = "User对象",required = true) User user){
        //调用UserService实现修改User
        userService.updateById(user);
        return new Result(true, StatusCode.OK,"修改成功");
    }


    /***
     * 新增User数据
     * @param User
     * @return
     */
    @Operation(summary = "User添加",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @PostMapping
    public Result add(@RequestBody @Parameter(name = "User对象",required = true) User User){
        //调用UserService实现添加User
        userService.add(User);
        return new Result(true, StatusCode.OK,"添加成功");
    }

    /***
     * 根据ID查询User数据
     * @param id
     * @return
     */
    @Operation(summary = "根据ID查询User",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameter(in = ParameterIn.PATH, name = "id", description = "主键ID", required = true)
    @GetMapping("/{id}")
    public Result<User> findById(@PathVariable Long id){
        //调用UserService实现根据主键查询User
        User User = userService.findById(id);
        return new Result<com.xiaohong.user.pojo.User>(true, StatusCode.OK,"查询成功", User);
    }

    /***
     * 根据手机号查询User数据
     * @param phone
     * @return
     */
    @Operation(summary = "根据手机号查询User",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameter(in = ParameterIn.PATH, name = "phone", description = "手机号", required = true)
    @GetMapping("/phone/{phone}")
    public Result<User> findByPhone(@PathVariable String phone){
        //调用UserService实现根据主键查询User
        User user1 = new User();
        user1.setPhone(phone);
        User user = userService.findList(user1).get(0);
        return new Result<User>(true, StatusCode.OK,"查询成功", user);
    }

    /***
     * 查询User全部数据
     * @return
     */
    @Operation(summary = "查询所有User",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @GetMapping
    public Result<List<User>> findAll(){
        //调用UserService实现查询所有User
        List<User> list = userService.findAll();
        return new Result<List<User>>(true, StatusCode.OK,"查询成功",list) ;
    }

}
